import '../models/wiki_config.dart';
import 'config_service.dart';

/// 搜索服务 - 实现双语搜索功能
/// Search Service - Implement bilingual search functionality
class SearchService {
  static final SearchService _instance = SearchService._internal();
  factory SearchService() => _instance;
  SearchService._internal();

  final ConfigService _configService = ConfigService();

  /// 搜索Wiki站点 Search wiki sites
  Future<List<WikiItem>> searchWikis({
    required String query,
    String? category,
  }) async {
    if (query.trim().isEmpty) {
      return await getAllWikis(category: category);
    }

    try {
      final config = await _configService.getWikiConfig();
      final allWikis = config.wikis;

      // 过滤搜索结果 Filter search results
      final filteredWikis = allWikis.where((wiki) {
        // 分类过滤 Category filter
        if (category != null &&
            category.isNotEmpty &&
            wiki.category != category) {
          return false;
        }

        // 搜索匹配 Search matching
        return _matchesQuery(wiki, query.toLowerCase().trim());
      }).toList();

      // 按相关性排序 Sort by relevance
      filteredWikis.sort((a, b) =>
          _calculateRelevance(b, query) - _calculateRelevance(a, query));

      return filteredWikis;
    } catch (e) {
      print('Error searching wikis: $e');
      return [];
    }
  }

  /// 获取所有Wiki站点 Get all wiki sites
  Future<List<WikiItem>> getAllWikis({
    String? category,
  }) async {
    try {
      final config = await _configService.getWikiConfig();
      final allWikis = config.wikis;

      return allWikis.where((wiki) {
        // 分类过滤 Category filter
        if (category != null &&
            category.isNotEmpty &&
            wiki.category != category) {
          return false;
        }

        return true;
      }).toList();
    } catch (e) {
      print('Error getting all wikis: $e');
      return [];
    }
  }

  /// 根据分类获取Wiki站点 Get wiki sites by category
  Future<List<WikiItem>> getWikisByCategory(String category) async {
    return await getAllWikis(category: category);
  }

  /// 根据分类获取Wiki站点 Get wiki sites by category (别名方法)
  Future<List<WikiItem>> getWikiSitesByCategory(String category) async {
    return await getWikisByCategory(category);
  }

  /// 获取分类列表 Get categories
  Future<List<String>> getCategories() async {
    return await getAllCategories();
  }

  /// 获取热门Wiki站点 Get popular wiki sites (别名方法)
  Future<List<WikiItem>> getPopularWikiSites({int limit = 10}) async {
    return await getPopularWikis(limit: limit);
  }

  /// 搜索Wiki站点 Search wiki sites
  Future<List<WikiItem>> searchWikiSites(String query) async {
    return searchWikis(query: query);
  }

  /// 获取所有分类 Get all categories
  Future<List<String>> getAllCategories() async {
    try {
      final config = await _configService.getWikiConfig();
      final categories = config.wikis
          .map((wiki) => wiki.category)
          .where((category) => category.isNotEmpty)
          .toSet()
          .toList();

      categories.sort();
      return categories;
    } catch (e) {
      print('Error getting categories: $e');
      return [];
    }
  }

  /// 获取热门Wiki站点 Get popular wiki sites
  Future<List<WikiItem>> getPopularWikis({int limit = 10}) async {
    try {
      final allWikis = await getAllWikis();

      // 这里可以根据实际使用情况排序，目前按字母顺序
      // Here you can sort by actual usage, currently by alphabetical order
      allWikis.sort((a, b) => a.name.compareTo(b.name));

      return allWikis.take(limit).toList();
    } catch (e) {
      print('Error getting popular wikis: $e');
      return [];
    }
  }

  /// 根据ID获取Wiki站点 Get wiki site by ID
  Future<WikiItem?> getWikiById(String id) async {
    try {
      final config = await _configService.getWikiConfig();

      // 查找匹配的Wiki Find matching wiki
      for (final wiki in config.wikis) {
        if (wiki.id == id) {
          return wiki;
        }
      }

      // 如果没找到，打印调试信息但不抛出异常 If not found, print debug info but don't throw exception
      print(
          'Wiki with ID "$id" not found in configuration. Available wikis: ${config.wikis.map((w) => w.id).join(", ")}');
      return null;
    } catch (e) {
      print('Error getting wiki by ID "$id": $e');
      return null;
    }
  }

  /// 搜索建议 Search suggestions
  Future<List<String>> getSearchSuggestions(String query) async {
    if (query.trim().isEmpty) return [];

    try {
      final config = await _configService.getWikiConfig();
      final suggestions = <String>{};

      final lowerQuery = query.toLowerCase().trim();

      for (final wiki in config.wikis) {
        // 添加名称建议 Add name suggestions
        if (wiki.name.toLowerCase().contains(lowerQuery)) {
          suggestions.add(wiki.name);
        }
        if (wiki.nameCn.toLowerCase().contains(lowerQuery)) {
          suggestions.add(wiki.nameCn);
        }
        if (wiki.nameEn.toLowerCase().contains(lowerQuery)) {
          suggestions.add(wiki.nameEn);
        }

        // 添加标签建议 Add tag suggestions
        for (final tag in wiki.tags) {
          if (tag.toLowerCase().contains(lowerQuery)) {
            suggestions.add(tag);
          }
        }

        // 添加分类建议 Add category suggestions
        if (wiki.category.toLowerCase().contains(lowerQuery)) {
          suggestions.add(wiki.category);
        }
      }

      final suggestionList = suggestions.toList();
      suggestionList.sort((a, b) {
        // 优先显示以查询开头的建议 Prioritize suggestions starting with query
        final aStartsWith = a.toLowerCase().startsWith(lowerQuery);
        final bStartsWith = b.toLowerCase().startsWith(lowerQuery);

        if (aStartsWith && !bStartsWith) return -1;
        if (!aStartsWith && bStartsWith) return 1;

        return a.length.compareTo(b.length);
      });

      return suggestionList.take(10).toList();
    } catch (e) {
      print('Error getting search suggestions: $e');
      return [];
    }
  }

  /// 检查查询是否匹配Wiki Check if query matches wiki
  bool _matchesQuery(WikiItem wiki, String query) {
    // 检查名称匹配 Check name matching
    if (wiki.name.toLowerCase().contains(query) ||
        wiki.nameCn.toLowerCase().contains(query) ||
        wiki.nameEn.toLowerCase().contains(query)) {
      return true;
    }

    // 检查描述匹配 Check description matching
    if (wiki.description.toLowerCase().contains(query) ||
        wiki.descriptionCn.toLowerCase().contains(query)) {
      return true;
    }

    // 检查分类匹配 Check category matching
    if (wiki.category.toLowerCase().contains(query)) {
      return true;
    }

    // 检查标签匹配 Check tag matching
    for (final tag in wiki.tags) {
      if (tag.toLowerCase().contains(query)) {
        return true;
      }
    }

    // 检查模糊匹配 Check fuzzy matching
    return _fuzzyMatch(wiki, query);
  }

  /// 计算相关性分数 Calculate relevance score
  int _calculateRelevance(WikiItem wiki, String query) {
    int score = 0;
    final lowerQuery = query.toLowerCase();

    // 精确匹配得分更高 Exact matches get higher scores
    if (wiki.name.toLowerCase() == lowerQuery) score += 100;
    if (wiki.nameCn.toLowerCase() == lowerQuery) score += 100;
    if (wiki.nameEn.toLowerCase() == lowerQuery) score += 100;

    // 开头匹配 Starting matches
    if (wiki.name.toLowerCase().startsWith(lowerQuery)) score += 50;
    if (wiki.nameCn.toLowerCase().startsWith(lowerQuery)) score += 50;
    if (wiki.nameEn.toLowerCase().startsWith(lowerQuery)) score += 50;

    // 包含匹配 Contains matches
    if (wiki.name.toLowerCase().contains(lowerQuery)) score += 20;
    if (wiki.nameCn.toLowerCase().contains(lowerQuery)) score += 20;
    if (wiki.nameEn.toLowerCase().contains(lowerQuery)) score += 20;

    // 标签匹配 Tag matches
    for (final tag in wiki.tags) {
      if (tag.toLowerCase() == lowerQuery) score += 30;
      if (tag.toLowerCase().startsWith(lowerQuery)) score += 15;
      if (tag.toLowerCase().contains(lowerQuery)) score += 10;
    }

    // 分类匹配 Category matches
    if (wiki.category.toLowerCase().contains(lowerQuery)) score += 10;

    // 描述匹配 Description matches
    if (wiki.description.toLowerCase().contains(lowerQuery)) score += 5;
    if (wiki.descriptionCn.toLowerCase().contains(lowerQuery)) score += 5;

    return score;
  }

  /// 模糊匹配 Fuzzy matching
  bool _fuzzyMatch(WikiItem wiki, String query) {
    // 简单的模糊匹配实现 Simple fuzzy matching implementation
    final searchTexts = [
      wiki.name,
      wiki.nameCn,
      wiki.nameEn,
      wiki.description,
      wiki.descriptionCn,
      wiki.category,
      ...wiki.tags,
    ];

    for (final text in searchTexts) {
      if (_levenshteinDistance(text.toLowerCase(), query) <= 2) {
        return true;
      }
    }

    return false;
  }

  /// 计算编辑距离 Calculate Levenshtein distance
  int _levenshteinDistance(String s1, String s2) {
    if (s1.length < s2.length) {
      return _levenshteinDistance(s2, s1);
    }

    if (s2.isEmpty) {
      return s1.length;
    }

    List<int> previousRow = List.generate(s2.length + 1, (i) => i);

    for (int i = 0; i < s1.length; i++) {
      List<int> currentRow = [i + 1];

      for (int j = 0; j < s2.length; j++) {
        int insertions = previousRow[j + 1] + 1;
        int deletions = currentRow[j] + 1;
        int substitutions = previousRow[j] + (s1[i] != s2[j] ? 1 : 0);

        currentRow.add([insertions, deletions, substitutions]
            .reduce((a, b) => a < b ? a : b));
      }

      previousRow = currentRow;
    }

    return previousRow.last;
  }
}
